'''
Created on 2009-10-6

@author: ray
'''

from MsgMng import *


class FileInfo(object):
    
    def __init__(self, info):
        a = self.parseMsg(info)
        self.id = int(a[0])
        self.name = a[1]
        self.size = xstrToLong(a[2])
        self.lastModified = time.gmtime(xstrToLong(a[3]))
        self.type = xstrToLong(a[4])
        self.exAttr = a[5]
        
    def __str__(self):
        return "fileinfo:\r\nid = %d\nname = %s\r\nsize = %ld\r\nlastmodified = %s\r\ntype = %ld\r\nexAttr = %s" %(self.id, self.name, self.size, time.asctime(self.lastModified), self.type, self.exAttr)
    
    def parseMsg(self, info):
        attr = info.split(":", 5)
        if len(attr) < 6:
            print "invalid file message format"
        else:
            return attr           
        
        
class IPMsg(MsgMng):
    '''
    class implementing main commnication protocol
    '''

    def __init__(self, (addr, port)):
        MsgMng.__init__(self,(addr, port))
        self.packetLog = []
        self.hostmgr = HostsMgr()
        self.abStat = "on"
        self.absences = {"on":"atcive"}
        self.versionInfo = "Python-ipmsg"
        #self.hostmgr.addHost(self.local)
        
    def hostStatus(self):
        ''' Check whether IPMSG_DIALUPOPT,IPMSG_ABSENCEOPT
        ,IPMSG_FILEATTACHOPT,IPMSG_ENCRYPTOPT are avaible'''
        return IPMSG_ABSENCEOPT|IPMSG_FILEATTACHOPT
    
    def getNameAndStat(self):
        name = self.local.userName
        if self.local.nickName:
            name = self.local.nickName
        if not self.abStat:
            return name
        else:
            return "%s[%s]" %(name, self.abStat)
        
    def udpEvent(self, msg):
        ''' main dispatcher for msg event '''
        cmd = GET_MODE(msg.command)
        print "cmd = 0x%08x" %cmd
        if cmd == IPMSG_BR_ENTRY:
            self.MsgBrEntry(msg)
            return True
        elif cmd == IPMSG_BR_EXIT:
            self.MsgBrExit(msg)
            return True
        elif cmd == IPMSG_ANSENTRY:
            self.MsgAnsEntry(msg)
            return True
        elif cmd == IPMSG_BR_ABSENCE:
            self.MsgBrAbsence(msg)
            return True
        elif cmd == IPMSG_SENDMSG:
            self.MsgSendMsg(msg)
        elif cmd == IPMSG_RECVMSG:
            self.MsgRecvMsg(msg)
        elif cmd in [IPMSG_READMSG, IPMSG_ANSREADMSG]:
            self.MsgReadMsg(msg)
        elif cmd == IPMSG_BR_ISGETLIST2:
            self.MsgBrIsGetList(msg)
            return True
        elif cmd == IPMSG_OKGETLIST:
            self.MsgOkGetList(msg)
            return True
        elif cmd == IPMSG_GETLIST:
            self.MsgGetList(msg)
            return True
        elif cmd == IPMSG_ANSLIST:
            self.MsgAnsList(msg)
            return True
        elif cmd == IPMSG_GETINFO:
            self.MsgGetInfo(msg)
        elif cmd == IPMSG_SENDINFO:
            self.MsgSendInfo(msg)
        elif cmd == IPMSG_GETPUBKEY:
            self.MsgGetPubKey(msg)
        elif cmd == IPMSG_ANSPUBKEY:
            self.MsgAnsPubKey(msg)
        elif cmd == IPMSG_GETABSENCEINFO:
            self.MsgGetAbsenceInfo(msg)
        elif cmd == IPMSG_SENDABSENCEINFO:
            self.MsgSendAbsenceInfo(msg)
        elif cmd == IPMSG_RELEASEFILES:
            self.MsgReleaseFiles(msg)
        else:
            print "0x%08x unknown command!" %cmd
            return False
        
        self.packetLog.append((msg.packetNo, msg.host.addr, msg.host.portNo))
        return True
    
    # The following methods are specific event handlers
    def MsgBrEntry(self, msg):
        self.send(msg.host, IPMSG_ANSENTRY|self.hostStatus(), self.getNameAndStat(), self.local.groupName)
        self.hostmgr.addHost(msg.host)
        
    def MsgBrExit(self, msg):
        self.hostmgr.delHost(msg.host.addr, msg.host.portNo)
        
    def MsgAnsEntry(self, msg):
        msg.host.nickName = msg.msg
        msg.host.groupName = msg.exMsg
        msg.host.hostStatus = GET_OPT(msg.command)
        self.hostmgr.addHost(msg.host)
        return msg.host
        
    def MsgBrAbsence(self, msg):
        msg.host.nickName = msg.msg
        msg.host.groupName = msg.exMsg
        msg.host.hostStatus = GET_OPT(msg.command)
    
    def MsgSendMsg(self, msg):
        ''' Sealed or locked message implement later '''
        files = []
        if msg.command & IPMSG_SENDCHECKOPT:
            self.send(msg.host, IPMSG_RECVMSG, str(msg.packetNo), "")
        if msg.command & IPMSG_FILEATTACHOPT:
            files = self.recvFilesInfo(msg)
            #RecvFilesThread(self, msg, files).start()
        if  (msg.command & IPMSG_SECRETOPT) and (msg.command &IPMSG_PASSWORDOPT):
            self.send(msg.host, IPMSG_READMSG|IPMSG_READCHECKOPT, str(msg.packetNo), "")
        elif msg.command & IPMSG_SECRETOPT:
            self.send(msg.host, IPMSG_READMSG|IPMSG_READCHECKOPT, str(msg.packetNo), "")
        return files
    
    def MsgRecvMsg(self, msg):
        pass

    def MsgReadMsg(self, msg):
        if GET_MODE(msg.command) == IPMSG_READMSG:
            if msg.command & IPMSG_READCHECKOPT:
                self.send(msg.host, IPMSG_ANSREADMSG, str(msg.packetNo), "")
        else:
           pass

    def MsgBrIsGetList(self, msg):
        pass

    def MsgOkGetList(self, msg):
        pass
        
    def MsgGetList(self, msg):
        buf = ""
        for h in self.hostmgr:
            buf += "%s\a%s\a%ld\a%s\a%d\a%s\a%s\a" %(h.userName, h.hostName, h.hostStatus, h.addr, h.portNo, h.nickName, h.groupName)
        self.send(msg.host, IPMSG_ANSLIST, buf, "")
        
    def MsgAnsList(self, msg):
        pass
        
    def MsgGetInfo(self, msg):
        self.send(msg.host, IPMSG_SENDINFO, self.versionInfo, "")
    
    def MsgSendInfo(self, msg):
        pass

    def MsgGetPubKey(self, msg):
        pass
    
    def MsgAnsPubKey(self, msg):
        pass
        
    def MsgGetAbsenceInfo(self, msg):
        if self.abStat != '':
            self.send(msg.host, IPMSG_SENDABSENCEINFO, self.absences[self.abStat], "")
        else:
            self.send(msg.host, IPMSG_SENDABSENCEINFO, "Not absence mode", "")
        
    def MsgSendAbsenceInfo(self, msg):
        pass

    def MsgReleaseFiles(self, msg):
        pass
    
    def recvFilesInfo(self, msg):
        files = msg.exMsg.split("\x07")
        fsinfo = []
        for f in files:
            if f == "\x00":
                break
            fsinfo.append(FileInfo(f))
        return fsinfo
    
    def informRecvPercent(self, name, rlen, size):
        per = rlen*100/size
        sys.stdout.write("\r%s %d%%" %(name, per))
        if per == 100:
            print ""
    
    def informRecvDone(self):
        print "transfer is done" 
        
    def informSendDone(self, name):
        print "send %s complete" %name
        
    def sendMsg(self, h, msg, seal=False, lock=False, files=[]):
        cmd = IPMSG_SENDMSG|IPMSG_SENDCHECKOPT
        if seal:
            cmd |= IPMSG_SECRETOPT
        if lock:
            cmd |= IPMSG_PASSWORDOPT
        if files !=[]:
            cmd |= IPMSG_FILEATTACHOPT
            exmsg = self.makeSendFileInfo(files)
            packetNo = self.send(h, cmd, msg, exmsg)
            self.addSendFile((packetNo, files))
        else:
            self.send(h, cmd, msg, "")
        
    def broadcastOnline(self):
        self.send(("255.255.255.255", IPMSG_DEFAULT_PORT), IPMSG_BR_ENTRY, "", "")
